﻿using Common.Interfaces;
using Common.Models;
using Microsoft.AspNetCore.SignalR;
using Newtonsoft.Json;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;

#nullable disable

namespace Common.Services;

public class OnlineUserService : ISingletonDependency
{
    private ConcurrentDictionary<string, OnlineUser> OnlineUsers = new();
    private readonly HttpClient _httpClient;

    public OnlineUserService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task AddOnlineUser(HubCallerContext Context) 
    {
        var httpContext = Context.GetHttpContext();
        var connectionId = Context.ConnectionId;
        var ipAddress = httpContext?.Connection?.RemoteIpAddress;
        var userAgent = httpContext?.Request.Headers["User-Agent"];
        var userName = Context.User?.Identity?.Name ?? string.Empty;
        var userId = Context.User?.Claims?.FirstOrDefault()?.Value;

        if (!OnlineUsers.ContainsKey(connectionId)) 
        {
            var onlineUsers = new OnlineUser
            {
                ConnectionId = Context.ConnectionId,
                Address = await GetIpAddressInfoAsync(_httpClient, ipAddress?.ToString()),
                IpAddress = ipAddress?.ToString(),
                Browser = ParseBrowser(userAgent),
                UserAgent = userAgent,
                OS = ParseOperatingSystem(userAgent),
                Time = DateTime.Now,
                Username = userName,
                UserId = userId
            };

            OnlineUsers.TryAdd(Context.ConnectionId, onlineUsers);
        }     
    }

    /// <summary>
    /// 一个用户一共有四个ConnectionId
    /// 所以要移除两次才能移除干净
    /// </summary>
    /// <param name="connectionId"></param>
    public Task RemoveOfflineUser(string connectionId)
    {
        OnlineUsers.TryRemove(connectionId, out var removeUser);
        if (removeUser == null) 
            return Task.CompletedTask;

        var continueRemoveOfflineUsersByUsername = OnlineUsers.Values
            .Where(x => x.Username == removeUser.Username)
            .Select(group => group)
            .ToList();
        if (!continueRemoveOfflineUsersByUsername.Any()) 
            return Task.CompletedTask;

        foreach ( var remove in continueRemoveOfflineUsersByUsername)
            OnlineUsers.TryRemove(remove.ConnectionId, out var user);

        return Task.CompletedTask;
    }

    public IEnumerable<OnlineUser> GetOnlineUsers(string username = null)
    {
        return OnlineUsers.Values
            .GroupBy(g => new { g.Username, g.Browser })
            .Select(group => group.First())
            .ToList();
    }

    public string Parse(string userAgent)
    {
        if (string.IsNullOrWhiteSpace(userAgent))
        {
            return string.Empty;
        }

        string os = ParseOperatingSystem(userAgent);
        string browser = ParseBrowser(userAgent);

        return $"{os}-{browser}";
    }

    private string ParseBrowser(string userAgent)
    {
        if (string.IsNullOrWhiteSpace(userAgent))
        {
            return string.Empty;
        }
        string pattern = @"(MSIE|Edg(?:e)?|Opera|Chrome|Safari|Firefox)(?:/|\s|$)";

        Match match = Regex.Match(userAgent, pattern);
        if (match.Success)
        {
            if (userAgent.Contains("Edg"))
            {
                return "Edge";
            }
            return match.Groups[1].Value;
        }
        return "Unknown";
    }

    private string ParseOperatingSystem(string userAgent)
    {
        if (string.IsNullOrWhiteSpace(userAgent))
        {
            return string.Empty;
        }
        // 操作系统关键词列表
        string[] osKeywords = { "Windows", "Macintosh", "Linux", "Android", "iOS" };

        // 使用正则表达式匹配用户代理字符串中的操作系统关键词
        foreach (string keyword in osKeywords)
        {
            if (userAgent.Contains(keyword))
            {
                return keyword;
            }
        }

        // 如果没有匹配到任何操作系统关键词，则返回 Unknown
        return "Unknown";
    }

    static async Task<string> GetIpAddressInfoAsync(HttpClient httpClient, string ipAddress, string language="zh-CN")
    {
        if (ipAddress == "::1" || ipAddress == "127.0.0.1")
        {
            return "本机";
        }

        string apiUrl = $"http://ip-api.com/json/{ipAddress}?lang={language}";
        try
        {
            // 发送 GET 请求并获取响应
            HttpResponseMessage response = await httpClient.GetAsync(apiUrl);

            // 确保响应成功
            response.EnsureSuccessStatusCode();

            // 读取响应内容并返回
            var responseBody = await response.Content.ReadAsStringAsync();
            var data = JsonConvert.DeserializeObject<dynamic>(responseBody);
            return $"{data.country} {data.regionName} {data.city}";
        }
        catch (HttpRequestException)
        {
            return ipAddress;
        }
    }
}
